﻿using IPS.SP2013.DiagnosticsProvider;
using IPS.SP2013.Helper;
using Microsoft.SharePoint;
using Microsoft.SharePoint.IdentityModel.Pages;
using Microsoft.SharePoint.WebControls;
using System;
using System.Web;
using System.Web.UI.WebControls;

namespace IPS.SP2013.CustomLoginPage
{

    /// <summary>
    /// Code behind for IPS custom login page
    /// NOTE: you could create several pages inherits from this
    /// and override virtual methods to satisfy the requirements
    /// of each one of your custom login page
    /// </summary>
    public partial class IPSLogin : FormsSignInPage
    {

        /// <summary>
        /// Welcome message encoded literal control
        /// </summary>
        protected EncodedLiteral WelcomeMessage;

        #region Override Methods

        /// <summary>
        /// Overrides "OnLoad" method to customize the login page UI
        /// </summary>
        /// <param name="e"></param>
        protected override void OnLoad(EventArgs e)
        {
            base.OnLoad(e);

            // Customize UI
            this.CustomizeLoginPageUI();
        }

        /// <summary>
        /// Overrides "RedirectToSuccessUrl" method to execute required and optional tasks
        /// </summary>
        protected override void RedirectToSuccessUrl()
        {
            this.ExecuteRequiredTasks();
            this.ExecuteOptionalTasks();

            base.RedirectToSuccessUrl();
        }

        #endregion

        #region Virtual Methods

        /// <summary>
        /// Customize the login page UI:
        ///     - Set welcome text
        ///     - Hide the "Remember Me" option
        ///     - Set "Remember Me" option checked as default
        /// NOTE: modify this method to customize the login page UI
        /// as your own requirements
        /// </summary>
        protected virtual void CustomizeLoginPageUI()
        {
            LogProvider.WriteLogEntry(DiagnosticsProvider.Constants.CategoryNames.Infomation,
                                        "IPSLogin.CustomizeLoginPageUI(): Start");

            try
            {
                // Set welcome message
                this.WelcomeMessage.Text = IPSResxHelper.GetResourceValue(Constants.Resource_File_Name, Constants.Resource_WelcomeMsg_Key, SPContext.Current.Web.Language);

                // Hide "Remember Me" checkbox and set checked as true
                CheckBox checkBox;
                if ((checkBox = (this.signInControl.FindControl(Constants.Control_RememberMeId) as CheckBox)) != null)
                {
                    checkBox.Checked = true;
                    checkBox.Visible = false;
                }
                this.signInControl.RememberMeSet = true;
            }
            catch (Exception ex)
            {
                LogProvider.WriteLogEntry(DiagnosticsProvider.Constants.CategoryNames.Error,
                          "IPSLogin.CustomizeLoginPageUI(): " + ex.Message);
                return;
            }

            LogProvider.WriteLogEntry(DiagnosticsProvider.Constants.CategoryNames.Success,
                            "IPSLogin.CustomizeLoginPageUI(): End");
        }

        /// <summary>
        /// Execute optional tasks after successfully logged in
        ///     - Update "FedAuth" cookie expiration date
        /// NOTE: modify this method to customize the optional tasks
        /// as your own requirements
        /// </summary>
        protected virtual void ExecuteOptionalTasks()
        {
            LogProvider.WriteLogEntry(DiagnosticsProvider.Constants.CategoryNames.Infomation,
                            "IPSLogin.ExecuteOptionalTasks(): Start");

            try
            {
                // Update expiration date of "FedAuth" cookie 
                // if user has checked "Remember" option
                if (this.signInControl.RememberMeSet)
                {
                    // Set expiration date
                    DateTime expirationDate = DateTime.Now.AddHours(Constants.Cookie_Expiration_Hours);

                    // Update cookie
                    this.UpdateCookieExpirationDate(Constants.Cookie_FedAuth_Name, expirationDate);
                }
            }
            catch (Exception ex)
            {
                LogProvider.WriteLogEntry(DiagnosticsProvider.Constants.CategoryNames.Error,
                          "IPSLogin.ExecuteOptionalTasks(): " + ex.Message);
                return;
            }

            LogProvider.WriteLogEntry(DiagnosticsProvider.Constants.CategoryNames.Success,
                "IPSLogin.ExecuteOptionalTasks(): End");
        }

        #endregion

        #region Private Methods

        /// <summary>
        /// Execute required tasks after successfully logged in
        ///     - Add current site cookie to page response
        /// NOTE: modify this method to customize the required tasks
        /// as your own requirements
        /// </summary>
        private void ExecuteRequiredTasks()
        {
            LogProvider.WriteLogEntry(DiagnosticsProvider.Constants.CategoryNames.Infomation,
                "IPSLogin.ExecuteRequiredTasks(): Start");

            try
            {
                this.AddCurrentSiteCookie();
            }
            catch (Exception ex)
            {
                LogProvider.WriteLogEntry(DiagnosticsProvider.Constants.CategoryNames.Error,
                                          "IPSLogin.ExecuteRequiredTasks(): " + ex.Message);
                return;
            }

            LogProvider.WriteLogEntry(DiagnosticsProvider.Constants.CategoryNames.Success,
                "IPSLogin.ExecuteRequiredTasks(): End");
        }

        /// <summary>
        /// Add current site cookie indicating site ID and root web title
        /// </summary>
        private void AddCurrentSiteCookie()
        {
            LogProvider.WriteLogEntry(DiagnosticsProvider.Constants.CategoryNames.Infomation,
                                      "IPSLogin.AddCurrentSiteCookie(): Start");

            string siteId = string.Empty;
            string webTitle = string.Empty;

            try
            {
                // Add cookie to check that user has been logged in on this site collection
                if (SPContext.Current != null && SPContext.Current.Site != null)
                {
                    // Elevate privileges
                    SPSecurity.RunWithElevatedPrivileges(delegate()
                    {
                        // Create a new instance of current site collection
                        using (SPSite site = new SPSite(SPContext.Current.Site.ID))
                        {
                            // Get site id property
                            siteId = site.ID.ToString();

                            // Check if root web exists
                            if (site.RootWeb != null)
                            {
                                // Get root web title
                                webTitle = site.RootWeb.Title;

                                // Set cookie name
                                string cookieName = string.Concat(Constants.Cookie_IPS_Start, ".", siteId);

                                // Set expiration date
                                DateTime expirationDate = DateTime.Now.AddHours(Constants.Cookie_Expiration_Hours);

                                // Add page response cookie
                                this.AddPageResponseCookie(cookieName, webTitle, expirationDate);
                            }
                            else
                            {
                                LogProvider.WriteLogEntry(DiagnosticsProvider.Constants.CategoryNames.Warning,
                                                          "IPSLogin.AddCurrentSiteCookie(): Root web doesn't exist");
                            }
                        }
                    });
                }
                else
                {
                    LogProvider.WriteLogEntry(DiagnosticsProvider.Constants.CategoryNames.Warning,
                                              "IPSLogin.AddCurrentSiteCookie(): Unable to get current site from SPContext");
                }
            }
            catch (Exception ex)
            {
                LogProvider.WriteLogEntry(DiagnosticsProvider.Constants.CategoryNames.Error,
                                          "IPSLogin.AddCurrentSiteCookie(): " + ex.Message);
                return;
            }

            LogProvider.WriteLogEntry(DiagnosticsProvider.Constants.CategoryNames.Success,
                "IPSLogin.AddCurrentSiteCookie(): End");
        }

        /// <summary>
        /// Add cookie to page response
        /// </summary>
        /// <param name="cookieName">Cookie Name</param>
        /// <param name="cookieValue">Cookie Value</param>
        /// <param name="expirationDate">Cookie Expiration Date</param>
        private void AddPageResponseCookie(string cookieName, string cookieValue, DateTime expirationDate)
        {
            LogProvider.WriteLogEntry(DiagnosticsProvider.Constants.CategoryNames.Infomation,
                                      "IPSLogin.AddPageResponseCookie('" + cookieName + "'): Start");

            try
            {
                // Get cookie
                HttpCookie cookie = Page.Response.Cookies[cookieName];

                if (cookie == null)
                {
                    // Create cookie if no exists
                    Page.Response.Cookies.Add(new HttpCookie(cookieName));

                    // Get cookie
                    cookie = Page.Response.Cookies[cookieName];
                }

                cookie.Value = cookieValue;
                cookie.Expires = expirationDate;
            }
            catch (Exception ex)
            {
                LogProvider.WriteLogEntry(DiagnosticsProvider.Constants.CategoryNames.Error,
                                          "IPSLogin.AddPageResponseCookie('" + cookieName + "'): " + ex.Message);
                return;
            }

            LogProvider.WriteLogEntry(DiagnosticsProvider.Constants.CategoryNames.Success,
                                      "IPSLogin.AddPageResponseCookie('" + cookieName + "'): End");
        }

        /// <summary>
        /// Update the expiration date of existing cookie
        /// </summary>
        /// <param name="cookieName"></param>
        /// <param name="expirationDate"></param>
        private void UpdateCookieExpirationDate(string cookieName, DateTime expirationDate)
        {
            LogProvider.WriteLogEntry(DiagnosticsProvider.Constants.CategoryNames.Infomation,
                          "IPSLogin.UpdateCookieExpirationDate('" + cookieName + "'): Start");

            try
            {
                // Get cookie
                HttpCookie cookie = Page.Response.Cookies[cookieName];

                if (cookie == null)
                {
                    LogProvider.WriteLogEntry(DiagnosticsProvider.Constants.CategoryNames.Warning,
                                              "IPSLogin.UpdateCookieExpirationDate('" + cookieName + "'): " + "Cookie '" + cookieName + "' doesn't exist");
                }
                else
                {
                    cookie.Expires = expirationDate;
                }
            }
            catch (Exception ex)
            {
                LogProvider.WriteLogEntry(DiagnosticsProvider.Constants.CategoryNames.Error,
                                          "IPSLogin.UpdateCookieExpirationDate('" + cookieName + "'): " + ex.Message);
            }

            LogProvider.WriteLogEntry(DiagnosticsProvider.Constants.CategoryNames.Infomation,
              "IPSLogin.UpdateCookieExpirationDate('" + cookieName + "'): Start");
        }

        #endregion

    }

}
